package cn.itrigger;

/*
 * 根据apringcloud项目的controller生成feignClient
 *
 */

import cn.itrigger.model.InfoProperties;
import cn.itrigger.util.FileUtil;
import cn.itrigger.util.FreemarkerUtil;
import cn.itrigger.util.PropertyUtil;
import freemarker.template.TemplateException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Mojo(name = "generate")
public class FeignClientGeneratorMojo extends AbstractMojo {

    @Parameter(property = "project")
    private MavenProject project;

    @Parameter(property = "generator.outputDirectory",defaultValue = "${project.build.directory}/generated-sources/feign-generator")
    private File outputDirectory;

    @Parameter(property = "basedir",defaultValue = "${project.basedir}")
    private File baseDirectory;

    @Parameter(property = "config.file",defaultValue = "${project.basedir}/src/main/resources/feignGenerator.properties")
    private File configFile;

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        List<String> modules = project.getModules();
        if (null == modules || modules.isEmpty()) {
            System.out.println("项目结构不满足条件");
            return;
        }

        if (!configFile.exists()) {
            throw new MojoExecutionException("缺少配置文件," + configFile.toString());
        }

        InfoProperties infoProperties = null;
        try {
            infoProperties = PropertyUtil.parseProperties(configFile, InfoProperties.class);
            if (!modules.contains(infoProperties.getSourceModule())) {
                System.err.println("项目中缺少源模块"+infoProperties.getSourceModule());
                return;
            }
            if (!modules.contains(infoProperties.getTargetModule())) {
                System.err.println("项目中缺少目标模块"+infoProperties.getSourceModule());
                return;
            }
        } catch (IOException | ClassNotFoundException | IllegalAccessException | InstantiationException e) {
            System.err.println("配置文件解析异常");
            e.printStackTrace();
            return;
        }
        //初始化freemarker模板路径
        try {
            FreemarkerUtil.config(infoProperties);
            String baseDirectoryPath = baseDirectory.getPath();
            //需要生成feignclient的controller类
            List<File> files = new ArrayList<>();
            if (StringUtils.isNotBlank(infoProperties.getControllerPackage())) {
                String controllerPackagePath = new StringBuffer(baseDirectoryPath).append("/").append(infoProperties.getSourceModule()).
                        append("/src/main/java").append(infoProperties.getControllerPackage()).toString();
//                FileUtil.getFiles(controllerPackagePath,files);
                FileUtil.getFiles(controllerPackagePath, files, new FileFilter() {
                    @Override
                    public boolean accept(File file) {
                        return file.getPath().contains("controller") && !file.getPath().contains("BaseController");
                    }
                });
            }else if (StringUtils.isNotBlank(infoProperties.getBasePath())){
                String controllerPackagePath = new StringBuffer(baseDirectoryPath).append("/").append(infoProperties.getSourceModule()).
                        append("/src/main/java").append(infoProperties.getBasePath()).toString();
                FileUtil.getFiles(controllerPackagePath, files, new FileFilter() {
                    @Override
                    public boolean accept(File file) {
                        return file.getPath().contains("controller") && !file.getPath().contains("BaseController");
                    }
                });
            }else {
                System.err.println("没有配置controller的读取目录");
                return;
            }

            String feignPackagePath = new StringBuffer(baseDirectoryPath).append("/").append(infoProperties.getTargetModule()).
                    append("/src/main/java").append(infoProperties.getFeignPackage()).toString();
            if (!files.isEmpty()) {
                Map<String,Object> dataMap;
                for (File f : files) {
                    System.out.println(f.getName());
                    dataMap = new HashMap<>();
                    String feignClientName = f.getName().replace("Controller.java","FeignClient");
                    dataMap.put("feignName",feignClientName);
                    dataMap.put("feignPackage",infoProperties.getFeignPackage().replaceAll("/",".").substring(1));
                    Map<String, List<String>> map = parseController(f);
                    dataMap.put("importList",map.get("importList"));
                    dataMap.put("methodList",map.get("methodList"));
                    dataMap.put("feignUrl",infoProperties.getFeignUrl());
                    dataMap.put("appName",infoProperties.getAppName());
                    File feign = new File(new StringBuffer(feignPackagePath).append("/").append(feignClientName).append(".java").toString());
                    FreemarkerUtil.parseFreemarker("FeignClientTemplate.ftl",dataMap,feign);
                }
            }

        } catch (Exception e) {
            System.err.print("模板解析异常");
            e.printStackTrace();
        }finally {
            try {
                FreemarkerUtil.clearCache();
            }catch (Exception e) {}
        }

    }

    private Map<String,List<String>> parseController(File f) throws IOException {
        Map<String,List<String>> result = new HashMap<>();
        List<String> readLines = IOUtils.readLines(new FileInputStream(f), "UTF-8");

        List<String> importPackages = new ArrayList<>();
        List<String> methods = new ArrayList<>();

        result.put("importList",importPackages);
        result.put("methodList",methods);

        StringBuffer sb = null;
        boolean canSplit = false;
        boolean canStart = false;
        for (String s : readLines) {
            if (s.trim().startsWith("import") && !s.contains("io.swagger.annotations")) {
                importPackages.add(s);
            }
            if (canStart) {
                if (canSplit) {
                    if (s.contains("{")) {
                        sb.append(s.replace("{",";")).append("\n");
                        canSplit = false;
                        System.out.println(sb.toString());
                        methods.add(sb.toString());
                    }else {
                        if(!s.contains("@ApiOperation")) {
                            sb.append(s).append("\n");
                        }
                    }
                }else {
                    if (s.contains("@PostMapping") || s.contains("@RequestMapping") || s.contains("@PutMapping") || s.contains("@GetMapping") || s.contains("@DeleteMapping")) {
                        sb = new StringBuffer(s).append("\n");
                        canSplit = true;
                    }
                }
            }
            if (s.contains("public") && s.contains("class") && s.contains("Controller")) {
                canStart = true;
            }
        }

        return result;
    }
}
